package com.custom.action.condition;

import com.custom.action.condition.support.TableSupport;
import com.custom.action.core.TableSimpleSupport;
import com.custom.action.interfaces.ColumnParseHandler;
import com.custom.comm.utils.Constants;
import com.custom.comm.utils.CustomUtil;
import com.custom.comm.utils.JudgeUtil;
import com.custom.comm.utils.lambda.SFunction;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringJoiner;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 查询条件储存
 * @author   Xiao-Bai
 * @since  2022/3/5 23:07
 */
public abstract class ConditionWrapper<T> extends BaseCondition<T> {


    /**
     * 查询的列名
     * 若是查询单表（查询的实体中(包括父类)没有@DbRelated,@DbJoinTables之类的关联注解）则column为表字段，例如 name, age
     * 若是查询关联表字段，则需附带关联表别名，例如：tp.name, tp.age
     */
    private List<String> selectColumns;

    /**
     * 当前条件构造是否只进行单表查询
     */
    private Boolean primaryTable = false;

    /**
     * 上一次的拼接条件
     */
    private String lastCondition;

    /**
     * 排序
     */
    private StringJoiner orderBy;
    /**
     * 分组
     */
    private StringJoiner groupBy;
    /**
     * 筛选
     */
    private StringBuilder having;
    private List<Object> havingParams;

    /**
     * 是否开启别名
     */
    protected boolean enableAlias = true;

    protected String getLastCondition() {
        return lastCondition;
    }

    protected void setLastCondition(String lastCondition) {
        this.lastCondition = lastCondition;
    }

    public List<String> getSelectColumns() {
        return selectColumns;
    }

    protected void setSelectColumns(List<String> selectColumns) {
        this.selectColumns = selectColumns;
    }

    protected void addSelectColumns(List<String> columns) {
        if (columns == null) {
            return;
        }
        if (this.selectColumns == null) {
            this.selectColumns = new ArrayList<>();
        }
        this.selectColumns.addAll(columns);
    }

    public StringJoiner getOrderBy() {
        return orderBy;
    }

    public StringJoiner getGroupBy() {
        return groupBy;
    }

    public StringBuilder getHaving() {
        return having;
    }

    public List<Object> getHavingParams() {
        return havingParams;
    }


    /**
     * 参数注入后的sql条件
     * <p>
     * 原sql(a.name = ?, params = 20)
     * </p>
     * 返回sql(a.name = 20)
     */
    public String injectParamsConditional() {
        StringBuilder handleSqlBuilder = new StringBuilder(getFinalConditional());

        if (JudgeUtil.isNotEmpty(this.getCustomizeSql())) {
            handleSqlBuilder.append(this.getCustomizeSql());
        }
        if (JudgeUtil.isNotEmpty(this.groupBy)) {
            handleSqlBuilder.append(Constants.GROUP_BY).append(this.groupBy);
        }
        if (JudgeUtil.isNotEmpty(this.having)) {
            handleSqlBuilder.append(Constants.HAVING).append(this.having);
            getParamValues().addAll(this.havingParams);
        }
        if (JudgeUtil.isNotEmpty(this.orderBy)) {
            handleSqlBuilder.append(Constants.ORDER_BY).append(this.orderBy);
        }
        return CustomUtil.handleExecuteSql(handleSqlBuilder.toString(), getParamValues().toArray());
    }

    protected void wrapperInitialize(Class<T> entityClass, boolean enableAlias) {
        wrapperInitialize(entityClass);
        this.enableAlias = enableAlias;
    }

    /**
     * 结构初始化
     */
    protected void dataStructureInit() {
        super.dataStructureInit();
        this.lastCondition = Constants.EMPTY;
        this.orderBy = new StringJoiner(Constants.SEPARATOR_COMMA_2);
        this.groupBy = new StringJoiner(Constants.SEPARATOR_COMMA_2);
        this.having = new StringBuilder();
        this.havingParams = new ArrayList<>();
    }

    public Boolean getPrimaryTable() {
        return primaryTable;
    }

    protected void setPrimaryTable() {
        this.primaryTable = true;
    }

    protected void setPrimaryTable(boolean primaryTable) {
        this.primaryTable = primaryTable;
    }

    /**
     * 清除所有条件-即初始化
     */
    public void clear() {
        this.dataStructureInit();
        this.selectColumns = null;
        this.customizeSql = null;
        this.suffixSql = null;
        this.pageIndex = null;
        this.pageSize = null;
        this.hasPageParams = false;
        this.primaryTable = false;
    }

}
